package com.xmtlxx.web.controller.wms.service.impl;

import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.util.IdUtil;
import com.xmtlxx.web.controller.center.service.ICommonService;
import com.xmtlxx.web.controller.wms.service.IWarehouseService;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.xmtlxx.common.core.domain.PageQuery;
import com.xmtlxx.common.core.domain.entity.SysDept;
import com.xmtlxx.common.core.domain.entity.SysUser;
import com.xmtlxx.common.core.page.TableDataInfo;
import com.xmtlxx.common.enums.PropertyLogNode;
import com.xmtlxx.common.enums.PropertyLogType;
import com.xmtlxx.common.helper.LoginHelper;
import com.xmtlxx.common.utils.DateUtils;
import com.xmtlxx.common.utils.JsonUtils;
import com.xmtlxx.common.utils.StringUtils;
import com.xmtlxx.oms.domain.OperatorLog;
import com.xmtlxx.oms.domain.PropertyLog;
import com.xmtlxx.oms.domain.TaskDtl;
import com.xmtlxx.oms.domain.vo.TaskVo;
import com.xmtlxx.oms.mapper.OperatorLogMapper;
import com.xmtlxx.oms.mapper.PropertyLogMapper;
import com.xmtlxx.oms.mapper.TaskDtlMapper;
import com.xmtlxx.oms.mapper.TaskMapper;
import com.xmtlxx.system.domain.SysOss;
import com.xmtlxx.system.mapper.SysDeptMapper;
import com.xmtlxx.system.mapper.SysOssMapper;
import com.xmtlxx.system.mapper.SysUserMapper;
import com.xmtlxx.system.service.ISysNoticeService;
import com.xmtlxx.tms.domain.OrderDtl;
import com.xmtlxx.tms.domain.bo.OrderBo;
import com.xmtlxx.tms.domain.vo.OrderVo;
import com.xmtlxx.tms.mapper.OrderDtlMapper;
import com.xmtlxx.tms.mapper.OrderMapper;
import com.xmtlxx.wms.domain.Warehouse;
import com.xmtlxx.wms.domain.WarehouseDtl;
import com.xmtlxx.wms.domain.bo.WarehouseBo;
import com.xmtlxx.wms.domain.bo.WarehouseDtlBo;
import com.xmtlxx.wms.domain.vo.StoreVo;
import com.xmtlxx.wms.domain.vo.WarehouseDtlVo;
import com.xmtlxx.wms.domain.vo.WarehouseVo;
import com.xmtlxx.wms.mapper.StoreMapper;
import com.xmtlxx.wms.mapper.WarehouseDtlMapper;
import com.xmtlxx.wms.mapper.WarehouseMapper;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.util.*;
import java.util.stream.Collectors;

/**
 * 入库单Service业务层处理
 *
 * @author xmtlxx
 * @date 2022-08-15
 */
@Slf4j
@RequiredArgsConstructor
@Service
public class WarehouseServiceImpl implements IWarehouseService {

    private final WarehouseMapper baseMapper;

    private final WarehouseDtlMapper warehouseDtlMapper;

    private final SysOssMapper sysOssMapper;

    private final OrderMapper orderMapper;

    private final OrderDtlMapper orderDtlMapper;

    private final TaskMapper taskMapper;

    private final TaskDtlMapper taskDtlMapper;

    private final OperatorLogMapper logMapper;

    private final PropertyLogMapper propertyLogMapper;

    private final StoreMapper storeMapper;

    private final SysDeptMapper deptMapper;

    private final ISysNoticeService sysNoticeService;

    private final SysUserMapper sysUserMapper;

    private final ICommonService commonService;

    /**
     * 查询入库单
     *
     * @param id 入库单主键
     * @return 入库单
     */
    @Override
    public WarehouseVo queryById(String id){
        //return baseMapper.selectVoById(id);
        return baseMapper.selectWarehouseVoByID(id);
    }

    @Override
    public WarehouseVo queryByTaskId(String taskId) {
        return baseMapper.selectWarehouseVoByTaskId(taskId);
    }

    /**
     * 查询入库单列表
     *
     * @param bo 入库单
     * @return 入库单
     */
    @Override
    public TableDataInfo<WarehouseVo> queryPageList(WarehouseBo bo, PageQuery pageQuery) {
       // LambdaQueryWrapper<Warehouse> lqw = buildQueryWrapper(bo);
       // Page<WarehouseVo> result = baseMapper.selectVoPage(pageQuery.build(), lqw);
        Page<WarehouseVo> result = baseMapper.selectPageWarehouseList(pageQuery.build(), bo);
        if(result != null && result.getRecords() != null && result.getRecords().size() > 0){
            for (WarehouseVo vo:result.getRecords()){
                StoreVo storeVo = storeMapper.selectStoreVoByID(vo.getStoreId());
                TaskVo taskVo = taskMapper.selectVoById(vo.getTaskId());
                vo.setPropertyType(taskVo.getPropertyType());
//                if(storeVo != null && storeVo.getDeptId().equals(LoginHelper.getDeptId())){
//                    vo.setIsShow(true);
//                }else {
//                    vo.setIsShow(false);
//                }
                if(storeVo != null){
                    if(storeVo.getDeptId().equals(LoginHelper.getDeptId())){
                        vo.setIsShow(true);
                    }else {
                        vo.setIsShow(false);
                    }
                }else {
                    //仓库为空时，判定为所队移交至区级，获取申请单位的上级部门判断

                    if( taskVo != null && deptMapper.selectVoById(taskVo.getDeptId()).getParentId().equals(LoginHelper.getDeptId())){
                        vo.setIsShow(true);
                    }else {
                        vo.setIsShow(false);
                    }
                }

                if(LoginHelper.getLoginUser().getRolePermission().contains("qxcangguang") && vo.getIsValidate().equals("1")){
                    vo.setIsSubmit(true);
                }else {
                    vo.setIsSubmit(false);
                }

//                SysOssBo ossBo = new SysOssBo();
//                ossBo.setObjid(vo.getId());
//                ossBo.setBuss("wms_warehouse");
//                List<SysOss> oss = sysOssMapper.selectSysOssList(ossBo);
//                vo.setOss(oss);

                //获取物品名称
                String propertyNames = "";
                WarehouseDtlBo dtlBo = new WarehouseDtlBo();
                dtlBo.setWid(vo.getId());
                dtlBo.setDelFlag("0");
                List<WarehouseDtlVo> dtlVos = warehouseDtlMapper.selectWarehouseDtlList(dtlBo);
                if(dtlVos != null && dtlVos.size() > 0){
                    propertyNames = dtlVos.stream().map(WarehouseDtlVo::getName).collect(Collectors.joining("|"));
                }
                vo.setPropertyNames(propertyNames);
            }
        }
        return TableDataInfo.build(result);
    }

    /**
     * 查询入库单列表
     *
     * @param bo 入库单
     * @return 入库单
     */
    @Override
    public List<WarehouseVo> queryList(WarehouseBo bo) {
       // LambdaQueryWrapper<Warehouse> lqw = buildQueryWrapper(bo);
       // return baseMapper.selectVoList(lqw);
        return baseMapper.selectWarehouseList(bo);
    }

    private LambdaQueryWrapper<Warehouse> buildQueryWrapper(WarehouseBo bo) {
        Map<String, Object> params = bo.getParams();
        LambdaQueryWrapper<Warehouse> lqw = Wrappers.lambdaQuery();
        lqw.eq(StringUtils.isNotBlank(bo.getTaskId()), Warehouse::getTaskId, bo.getTaskId());
        lqw.eq(StringUtils.isNotBlank(bo.getStoreId()), Warehouse::getStoreId, bo.getStoreId());
        lqw.like(StringUtils.isNotBlank(bo.getWno()), Warehouse::getWno, bo.getWno());
        lqw.eq(StringUtils.isNotBlank(bo.getType()), Warehouse::getType, bo.getType());
        lqw.eq(bo.getDeptId() != null, Warehouse::getDeptId, bo.getDeptId());
        lqw.like(StringUtils.isNotBlank(bo.getName()), Warehouse::getName, bo.getName());
        lqw.eq(StringUtils.isNotBlank(bo.getTel()), Warehouse::getTel, bo.getTel());
        lqw.eq(StringUtils.isNotBlank(bo.getAddress()), Warehouse::getAddress, bo.getAddress());
        lqw.eq(StringUtils.isNotBlank(bo.getFlag()), Warehouse::getFlag, bo.getFlag());
        lqw.between(params.get("beginCreateTime") != null && params.get("endCreateTime") != null,
            Warehouse::getCreateTime ,params.get("beginCreateTime"), params.get("endCreateTime"));
        lqw.eq(StringUtils.isNotBlank(bo.getCreateBy()), Warehouse::getCreateBy, bo.getCreateBy());
        lqw.between(params.get("beginUpdateTime") != null && params.get("endUpdateTime") != null,
            Warehouse::getUpdateTime ,params.get("beginUpdateTime"), params.get("endUpdateTime"));
        lqw.eq(StringUtils.isNotBlank(bo.getUpdateBy()), Warehouse::getUpdateBy, bo.getUpdateBy());
        lqw.eq(StringUtils.isNotBlank(bo.getDelFlag()), Warehouse::getDelFlag, bo.getDelFlag());
        return lqw;
    }

    /**
     * 新增入库单
     *
     * @param bo 入库单
     * @return 结果
     */
    @Override
    @Transactional(rollbackFor = Exception.class)
    public Warehouse insertByBo(WarehouseBo bo) {
        Warehouse add = BeanUtil.toBean(bo, Warehouse.class);
        validEntityBeforeSave(add);

        //填充UUID
        add.setId(IdUtil.simpleUUID());
        add.setDelFlag("0");

        List<SysOss> ossList = new ArrayList<>();
        if(bo.getOss() != null && bo.getOss().size() > 0){
            ossList = bo.getOss().stream().map(item->{
                //是否下发的图片
                if(StringUtils.isNotEmpty(add.getTaskId())){
                    SysOss oss = new SysOss();
                    BeanUtil.copyProperties(item,oss,"ossId");
                    oss.setBuss("wms_warehouse");
                    oss.setObjid(add.getId());
                    sysOssMapper.insert(oss);
                    return oss;
                }else {
                    item.setBuss("wms_warehouse");
                    item.setObjid(add.getId());
                    sysOssMapper.updateById(item);
                    return item;
                }
            }).collect(Collectors.toList());
        }

        List<WarehouseDtl> dtls = new ArrayList<>();
        if(bo.getItems() != null && bo.getItems().size() > 0){
            List<SysOss> finalOssList = ossList;
            dtls = bo.getItems().stream().map(item->{
                WarehouseDtl dtl = BeanUtil.toBean(item,WarehouseDtl.class);
                dtl.setId(IdUtil.simpleUUID());
                dtl.setWid(add.getId());
                dtl.setDelFlag("0");
                dtl.setStatus("0");
                String logContent = "下发入库单：(物品编号："+item.getPno()+"，物品名称："+item.getName()+")";
                /**
                 * 物品日志
                 */
//                commonService.savePropertyLog(dtl.getPno(),add.getId(),dtl.getName(),PropertyLogType.WAREHOUSE.getCode(),logContent,
//                    add.getDeptId(),JsonUtils.toJsonString(dtl),add.getStoreId(),dtl.getNums(), finalOssList);
                return dtl;
            }).collect(Collectors.toList());

            warehouseDtlMapper.insertBatch(dtls);
        }
        Long nums = dtls.stream().mapToLong(item-> item.getNums()).sum();
        add.setNums(nums);
        boolean flag = baseMapper.insert(add) > 0;
        /**
         * 操作日志
         */
//        commonService.saveOperatorLog(StringUtils.isNotEmpty(add.getTaskId())?add.getTaskId():add.getId(),"wms",PropertyLogType.WAREHOUSE.getInfo());
        bo.setId(add.getId());
        return add;
    }

    /**
     * 修改入库单
     *
     * @param bo 入库单
     * @return 结果
     */
    @Override
    @Transactional(rollbackFor = Exception.class)
    public Warehouse updateByBo(WarehouseBo bo) {
        Warehouse update = BeanUtil.toBean(bo, Warehouse.class);
        validEntityBeforeSave(update);
        Long nums = update.getNums();
        /**
         * 查询原明细数据
         */
        WarehouseDtlBo dtlBo = new WarehouseDtlBo();
        dtlBo.setWid(update.getId());
        List<WarehouseDtlVo> olds = warehouseDtlMapper.selectWarehouseDtlList(dtlBo);

        List<WarehouseDtl> dtls = new ArrayList<>();

        if(bo.getItems() != null && bo.getItems().size() > 0){
            dtls = bo.getItems().stream().map(item->{
                WarehouseDtl dtl = new WarehouseDtl();
                BeanUtil.copyProperties(item,dtl);
                if(StringUtils.isEmpty(dtl.getId())){//修改后的物品
                    dtl.setId(IdUtil.simpleUUID());
                    dtl.setDelFlag("0");
                    dtl.setStatus("0");
                    dtl.setWid(update.getId());
                }
                /**
                 * 迭代查询移除的明细
                 */
                Iterator iterator = olds.iterator();
                while(iterator.hasNext()){
                    WarehouseDtlVo warehouseDtl = (WarehouseDtlVo) iterator.next();
                    if(warehouseDtl.getId().equals(dtl.getId())){
                        iterator.remove();
                    }
                }

                return dtl;
            }).collect(Collectors.toList());

            nums = dtls.stream().mapToLong(item-> item.getNums()).sum();
        }
        update.setNums(nums);

        if(dtls.size() > 0){
            warehouseDtlMapper.insertOrUpdateBatch(dtls);
        }
        //已删除的物品处理：删除dtl表、回退可移交状态
        if(bo.getItems() != null && bo.getItems().size() > 0 && olds != null && olds.size() > 0){
            olds.forEach(item -> {
                warehouseDtlMapper.deleteVoById(item.getId());
            });
        }

        /**
         * isValidate 跨级确认
         * 0-无需确认 1-需确认 2-已确认
         */
        if(bo.getIsValidate().equals("2")){
            update.setValidateTime(new Date());//确认市级
            update.setValidater(LoginHelper.getUsername());//确认人
            /**
             * 操作日志
             */
//            commonService.saveOperatorLog(StringUtils.isNotEmpty(update.getTaskId())?update.getTaskId():update.getId(),"wms","区级确认入库单");

            //消息通知
            //消息接收人
            List<String> toUsers = new ArrayList<>();
            if(update.getDeptId() != null){
                //申请人
                SysUser sysUser = sysUserMapper.selectOne(new LambdaQueryWrapper<SysUser>().eq(SysUser::getDeptId,update.getDeptId()));
                toUsers.add(sysUser.getUserId().toString());
            }


            //仓库
            TaskVo task = taskMapper.selectTaskVoByID(update.getId());
            if(task != null){
                StoreVo storeVo = storeMapper.selectVoById(task.getStoreId());
                if(storeVo != null){
                    SysUser storeUser = sysUserMapper.selectOne(new LambdaQueryWrapper<SysUser>().eq(SysUser::getDeptId,storeVo.getDeptId()));
                    if(storeUser != null){
                        toUsers.add(storeUser.getUserId().toString());
                    }
                }
            }
            if(toUsers != null && toUsers.size() > 0){
                String contentInfo = "您有1条入库单已确认，请及时查阅！";
                commonService.sendSysNotice("1",toUsers,update.getDeptId(),"入库单确认提醒",contentInfo,"{\"page\":\"/pagesOMS/staging/index\"}");
            }
        }
        baseMapper.updateById(update);
        return update;
    }

    @Override
    public Boolean updateByWarehouse(WarehouseBo bo) {
        Warehouse update = BeanUtil.toBean(bo, Warehouse.class);
        validEntityBeforeSave(update);
        return baseMapper.updateById(update) > 0;
    }

    /**
     * 保存前的数据校验
     *
     * @param entity 实体类数据
     */
    private void validEntityBeforeSave(Warehouse entity){
        //TODO 做一些数据校验,如唯一约束
    }

    /**
     * 批量删除入库单
     *
     * @param ids 需要删除的入库单主键
     * @return 结果
     */
    @Override
    @Transactional(rollbackFor = Exception.class)
    public Boolean deleteWithValidByIds(Collection<String> ids, Boolean isValid) {
        if(isValid){
            //TODO 做一些业务上的校验,判断是否需要校验
        }
        return baseMapper.deleteBatchIds(ids) > 0;
    }

    public String getNo(){
        LambdaQueryWrapper<Warehouse> lqw = Wrappers.lambdaQuery();
        Long maxNumObject = baseMapper.selectCount(lqw);
        String num = "";
        String todayStr = DateUtils.date2String(new Date(), "yyMMdd");

        if (maxNumObject == null) {
            num = todayStr + "000001";
        } else {
            String maxnumStr = "00000" + maxNumObject.toString();
            String maxnumNo = maxnumStr.substring(maxnumStr.length() - 6, maxnumStr.length());
            String nextnumNo = StringUtils.nextNo(maxnumNo, 6);
            num = todayStr + nextnumNo;
        }
        return num;
    }

    public void updateOrder(String taskId,List<WarehouseDtlVo> items){
        OrderBo orderBo = new OrderBo();
        orderBo.setTaskId(taskId);
        List<OrderVo> orderVos = orderMapper.selectOrderList(orderBo);
        List<OrderDtl> dtls = new ArrayList<>();
        if(orderVos != null && orderVos.size() > 0){
            OrderVo vo = orderVos.get(0);
            for (WarehouseDtlVo item:items){
                OrderDtl dtl = BeanUtil.toBean(item,OrderDtl.class);

                LambdaQueryWrapper<OrderDtl> lqw = Wrappers.lambdaQuery();
                lqw.eq(StringUtils.isNotBlank(vo.getId()), OrderDtl::getOrderId, vo.getId());
                lqw.eq(StringUtils.isNotBlank(item.getPno()), OrderDtl::getPno, item.getPno());
                OrderDtl orderDtl = orderDtlMapper.selectOne(lqw);

                if(StringUtils.isEmpty(item.getId()) && orderDtl == null){
                    dtl.setId(IdUtil.simpleUUID());
                    dtl.setOrderId(vo.getId());
                    dtl.setDelFlag("0");
                    dtl.setStatus("0");
                }else {
                    dtl.setId(orderDtl.getId());
                }
                dtls.add(dtl);
            }
        }
        if(dtls != null && dtls.size() > 0){
            orderDtlMapper.insertOrUpdateBatch(dtls);
        }
    }

    public void updateTask(String taskId,List<WarehouseDtlVo> items){
        TaskVo taskVo = taskMapper.selectTaskVoByID(taskId);
        List<TaskDtl> dtls = new ArrayList<>();
        if(taskVo != null){
            for (WarehouseDtlVo item:items){
                TaskDtl dtl = BeanUtil.toBean(item,TaskDtl.class);

                LambdaQueryWrapper<TaskDtl> lqw = Wrappers.lambdaQuery();
                lqw.eq(StringUtils.isNotBlank(taskVo.getId()), TaskDtl::getTaskId, taskVo.getId());
                lqw.eq(StringUtils.isNotBlank(item.getPno()), TaskDtl::getPno, item.getPno());
                TaskDtl taskDtl = taskDtlMapper.selectOne(lqw);

                if(StringUtils.isEmpty(item.getId()) && taskDtl == null){
                    dtl.setId(IdUtil.simpleUUID());
                    dtl.setTaskId(taskVo.getId());
                    dtl.setDelFlag("0");
                }else {
                    dtl.setId(taskDtl.getId());
                }
                dtls.add(dtl);
            }
        }
        if(dtls != null && dtls.size() > 0){
            taskDtlMapper.insertOrUpdateBatch(dtls);
        }
    }

    //操作日志添加
    public void  addOperatorLog(String objid,String type,String content){
        OperatorLog log = new OperatorLog();
        log.setId(IdUtil.simpleUUID());
        log.setObjid(objid);
        log.setDelFlag("0");
        log.setLogTime(new Date());
        log.setUserId(LoginHelper.getUserId());
        log.setOperator(LoginHelper.getNickname());
        log.setLogType(type);
        log.setContent(content);
        logMapper.insert(log);
    }

    //财物日志添加
    private  PropertyLog  saveLog(WarehouseDtl dtl,String objid, String storeId, String content,Long deptId,List<SysOss> osses){
        PropertyLog propertyLog = new PropertyLog();

        BeanUtil.copyProperties(dtl,propertyLog,"id");
        propertyLog.setId(IdUtil.simpleUUID());
        propertyLog.setObjid(objid);
        propertyLog.setLogTime(new Date());
        propertyLog.setLogType(PropertyLogType.WAREHOUSE.getCode());//0-移交登记 1-入库 2-出库 3-调用 4-处置 5-交接 6-上架 7-挑拣
        propertyLog.setContent(content);
        propertyLog.setStoreId(storeId);
        propertyLog.setReceiveDept(dtl.getDeptId());
        propertyLog.setUserId(LoginHelper.getUserId());
        propertyLog.setOperator(LoginHelper.getNickname());
        propertyLog.setInfo(JsonUtils.toJsonString(dtl));
        propertyLog.setDelFlag("0");

        SysDept dept = deptMapper.selectById(LoginHelper.getDeptId());
        propertyLog.setNode(PropertyLogNode.getNodeCodeByBuss(dept.getLevel(),"1"));
        propertyLogMapper.insert(propertyLog);
        if(osses != null && osses.size() > 0){
            for(SysOss oss : osses){
                SysOss copyOss = new SysOss();
                BeanUtil.copyProperties(oss,copyOss,"ossId");
                copyOss.setObjid(propertyLog.getId());
                copyOss.setBuss("propertyLog");
                sysOssMapper.insert(copyOss);
            }
        }
        return  propertyLog;
    }
}
